package gudaziEx.service;

import com.alibaba.fastjson.JSONArray;
import commons.entity.Constant;
import commons.entity.NativeCp;
import commons.util.*;
import fgoScript.constant.GameConstant;
import fgoScript.entity.PointColor;
import fgoScript.exception.AppNeedRestartException;
import fgoScript.exception.AppNeedStopException;
import fgoScript.exception.AppNeedUpdateException;
import gudaziEx.entity.ClickChain;
import gudaziEx.entity.ClickUnit;
import gudaziEx.entity.RunningChain;
import gudaziEx.util.ChainUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledFuture;

public class ClickManage {
    private static final Logger LOGGER = LogManager.getLogger(ClickManage.class);
    private boolean go;
    private boolean allStop;
    private boolean shiftOut;
    private int reBootCounts;
    private String goInfor="";
    /** 前台线程 **/
    private ThreadPoolTaskExecutor frontExcutor;
    /** 常住线程 **/
    private ThreadPoolTaskExecutor guardExcutor;
    /** 常住main线程 **/
    private ThreadPoolTaskExecutor mainExcutor;
    // 计划任务对象
    private TaskScheduler scheduler;
    // 计划future对象
    private ScheduledFuture future;
    private Future scrollFuture;

    // 计划future对象
//    private Future scrollFuture;


//    public void setScrollFuture(Future scrollFuture) {
//        this.scrollFuture = scrollFuture;
//    }

    public void setScheduler(TaskScheduler scheduler) {
        this.scheduler = scheduler;
    }

    public void setFuture(ScheduledFuture future) {
        this.future = future;
    }

    public void tempToggle(){
        if (frontExcutor.getActiveCount() == 0){
            doClick("temp",false);
        }else{
            stopClick();
        }
    }
    private ClickChain getClickChainByFileName(String fileName){
        ClickChain cc = null;
        try {
            cc = ChainUtil.getClickChain(fileName);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(),e);

        }
        return cc;
    }
    public void Toggle(String name,boolean closeAfterFinish){
        if (frontExcutor.getActiveCount() == 0){
            doClick(name,true);
            if(closeAfterFinish){
                ClickChain cc = getClickChainByFileName(name);
                ProcessDealUtil.closeLD(cc.getLdIndex());
            }
        }else{
            stopClick();
        }
    }
    /** 执行操作链 **/
    private void doClick(String chainFilePathName,boolean checkLogin){
        setGo(true);
        Future ft ;
        guardExcutor.execute(() -> {

        });
        ft = frontExcutor.submit(() -> {
            doClickForExcutor(chainFilePathName, checkLogin, false);
        });
        ThreadUtil.waitUntilFutureFinished(ft);
        LOGGER.info("脚本路径：" + chainFilePathName + " 点击结束，frontExcutor释放！");

    }
    /** 执行操作链 **/
    public void autoScroll(){
        if(null == scrollFuture || scrollFuture.isDone()){
            System.out.println("未执行，开始执行!");

        }else{
            System.out.println("已经执行执行，停止!");

            GameUtil.setSTOP_SCRIPT(true);
            return;
        }
        Point temp = null;

        scrollFuture = mainExcutor.submit(new Runnable() {
            @Override
            public void run() {
                int factor = 1;
                int delay = getFactor();
                int step = getStep();
                Point point = GameUtil.getMousePosition();
                Point tempPoint;
                int x = (int)point.getX();
                int y = (int)point.getY();
                for (int i = 0; !GameUtil.isSTOP_SCRIPT(); i++) {
                    if(i==0){
                        GameUtil.getMymouse().mousePress();
                    }
                    tempPoint = new Point(x ,y-i*factor);
                    try {
                        GameUtil.getMymouse().mouseMoveByPoint(tempPoint,false,false);
                    } catch (AppNeedStopException e) {
                        e.printStackTrace();
                    }

                    GameUtil.delay(delay);
                    if(i == step){
                        i=-1;
                        GameUtil.getMymouse().mouseRelease();
                        try {
                            GameUtil.getMymouse().mouseMoveByPoint(point,false,false);
                        } catch (AppNeedStopException e) {
                            e.printStackTrace();
                        }
                    }

                }
                GameUtil.setSTOP_SCRIPT(false);
                GameUtil.getMymouse().mouseRelease();

            }
        });

    }
    /** 执行操作链 **/
    public void autoWhell(int foward){
        if(null == scrollFuture || scrollFuture.isDone()){
            System.out.println("未执行，开始执行!");

        }else{
            System.out.println("已经执行执行，停止!");

            GameUtil.setSTOP_SCRIPT(true);
            return;
        }

        int restTime = getRestTimeForWhell();
        int RestStep = getRestStepForWhell();
        if(restTime!=0 && RestStep!=0){
            autoWhellforStay(foward);
        }else {
            autoWhellforGo(foward);
        }

    }
    /** 执行操作链 **/
    private void autoWhellforGo(int foward){
        scrollFuture = mainExcutor.submit(new Runnable() {
            @Override
            public void run() {
                int delay = getFactorForWhell();
                int step = getStepForWhell();
                int num = foward*step;

                for (int i = 0; !GameUtil.isSTOP_SCRIPT(); i++) {
                    GameUtil.getMymouse().mouseWhell(num);
                    GameUtil.delay(delay);
                }
                GameUtil.setSTOP_SCRIPT(false);
            }
        });

    }
    /** 执行操作链 **/
    private void autoWhellforStay(int foward){
        scrollFuture = mainExcutor.submit(new Runnable() {
            @Override
            public void run() {
                int delay = getFactorForWhell();
                int step = getStepForWhell();
                int restTime = getRestTimeForWhell();
                int RestStep = getRestStepForWhell();
                int num = foward*step;
                int count = 0;
                for (int i = 0; !GameUtil.isSTOP_SCRIPT(); i++) {
                    GameUtil.getMymouse().mouseWhell(num);
                    GameUtil.delay(delay);
                    count+=step;
                    if( count > RestStep){
                        count = 0;
                        GameUtil.delay(restTime);
                    }
                }
                GameUtil.setSTOP_SCRIPT(false);
            }
        });

    }
    private int getFactor(){
        String multiFactor = PropertiesUtil.getValueFromFileNameAndKey("multiFactorForScroll" , "changeButton_" + NativeCp.getUserName(),"");
        int factor = Integer.parseInt(multiFactor.trim());
        return factor;
    }
    private int getFactorForWhell(){
        String multiFactor = PropertiesUtil.getValueFromFileNameAndKey("multiFactorForWhell" , "changeButton_" + NativeCp.getUserName(),"");
        int factor = Integer.parseInt(multiFactor.trim());
        return factor;
    }
    public static int getFactorForSdMultiFactor(){
        String multiFactor = PropertiesUtil.getValueFromFileNameAndKey("sdMultiFactor" , "changeButton_" + NativeCp.getUserName(),"");
        int factor = Integer.parseInt(multiFactor.trim());
        return factor;
    }
    private int getRestStepForWhell(){
        String multiFactor = PropertiesUtil.getValueFromFileNameAndKey("restStepForWhell" , "changeButton_" + NativeCp.getUserName(),"");
        int factor = Integer.parseInt(multiFactor.trim());
        return factor;
    }
    private int getRestTimeForWhell(){
        String multiFactor = PropertiesUtil.getValueFromFileNameAndKey("restTimeForWhell" , "changeButton_" + NativeCp.getUserName(),"");
        int factor = Integer.parseInt(multiFactor.trim());
        return factor;
    }
    private int getStep(){
        String multiFactor = PropertiesUtil.getValueFromFileNameAndKey("scrollStep" , "changeButton_" + NativeCp.getUserName(),"");
        int step = Integer.parseInt(multiFactor.trim());
        return step;
    }
    private int getStepForWhell(){
        String multiFactor = PropertiesUtil.getValueFromFileNameAndKey("whellStep" , "changeButton_" + NativeCp.getUserName(),"");
        int step = Integer.parseInt(multiFactor.trim());
        return step;
    }
    private void doClickForExcutor(String chainFilePathName,boolean checkLogin, boolean ifReBoot){
        try {
            ClickChain cc = null;
            try {
                cc = ChainUtil.getClickChain(chainFilePathName);
            } catch (Exception e) {
                LOGGER.error(e.getMessage(),e);
            }
            if(goInfor.contains("" + cc.getLdIndex())){
                goInfor = "";
                LOGGER.error("该账户登录异常，请调整");
                throw new AppNeedStopException();
            }
            if (reBootCounts == 5){
                reBootCounts = 0;
                goInfor = cc.getLdIndex() + "_";
                throw new AppNeedStopException();
            }
            if (checkLogin){
                doLogin(chainFilePathName, ifReBoot);
            }
            doClickInner(chainFilePathName);
        } catch (AppNeedRestartException e) {
            LOGGER.error(e.getMessage(),e);
            reBootFromRunningChain();
        } catch (AppNeedStopException e) {
            LOGGER.error(e.getMessage(),e);
            closeLdForRunning(chainFilePathName);
        } catch (AppNeedUpdateException e) {
            LOGGER.error(e.getMessage(),e);
        } catch (Exception e){
            LOGGER.error(e.getMessage(),e);
        }
    }
    /** 定时任务 **/
    public void doCornRunnable(String corn,String runnableName){
        CronTrigger ct= new CronTrigger(corn);
        String startegy = PropertiesUtil.getValueFromFileNameAndKey("sleepMode" , "changeButton_" + NativeCp.getUserName(), "");
        setFuture(scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                LOGGER.info("首次执行runnable定时任务：" + runnableName);
                if (oneStepRunnable(runnableName, true)
                && "睡眠".equals(startegy)) {
                    goToSleep(ct);
                }
            }
        },new Date(System.currentTimeMillis()+2000)));
        GameUtil.delay(5000);
        scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                LOGGER.info("执行runnable定时任务：" + runnableName);
                if (oneStepRunnable(runnableName,false)
                        && "睡眠".equals(startegy)) {
                    goToSleep(ct);
                }
            }
        }, ct);

        while (!future.isDone()){
            GameUtil.delay(5000);
        }
    }

    private void goToSleep(CronTrigger ct){
        Date dt = ct.nextExecutionTime(new TriggerContext() {
            @Override
            public Date lastScheduledExecutionTime() {
                return null;
            }

            @Override
            public Date lastActualExecutionTime() {
                return null;
            }

            @Override
            public Date lastCompletionTime() {
                return new Date();
            }
        });
        Calendar cd = Calendar.getInstance();
        cd.setTime(new Date());
        boolean IF_ShutDown_LastRound = Boolean.parseBoolean(GameUtil.getValueFromConfig("IF_ShutDown_LastRound"));
        if(cd.get(Calendar.HOUR_OF_DAY)  < 3 && IF_ShutDown_LastRound) {
            ProcessDealUtil.closeComputer();
        }else if(cd.getTime().getTime() + 10 * 60 * 1000 < dt.getTime()
                && cd.get(Calendar.HOUR_OF_DAY)  > 3) {
            mainExcutor.execute(new Runnable() {
                @Override
                public void run() {
                    GameUtil.delay(5000);
                    ProcessDealUtil.sleepComputer();
                }
            });

        }
    }

    private void reBootFromRunningChain(){
        RunningChain rc = ChainUtil.getRunningChain();
        reBootCounts++;
        doClickForExcutor(rc.getAutoChainName(), true, true);
    }

    /**
     *  执行 Ex 脚本 和 runnable任务 Ex脚本必须在运行当中
     * @param runnableName
     * @param firstRunning
     */
    private boolean oneStepRunnable(String runnableName,boolean firstRunning){
        if (!future.isDone() && !firstRunning){
            LOGGER.info("首次任务还未完成！此次忽略！");
            return false;
        }
        RunningChain rc = ChainUtil.getRunningChain();
        String autoChainName = rc.getAutoChainName();
        if(frontExcutor.getActiveCount() != 0){
            // 执行 A T 切出脚本（自动战斗 或者 停留在开始战斗画面）
            waitUntilShiftOut();
            if (autoChainName.contains("TEAM")){
                // T 关闭可能运行中的雷电模拟器
                closeLdForRunning(autoChainName);
                rc.setLogin(true);
                ChainUtil.saveRunningChain(rc);
                // 执行 T 挂机脚本
                runMain(rc.getDailyChainName(),true);
                waitUntilShiftOut();
                ChainUtil.saveRunningChain(rc);

            }
            // 执行 A T runnable任务
            waitUntilRunnableFinished(runnableName);
            // 执行 A 返回脚本
//            String finalPath = rc.getShiftIningPath();
            if (!autoChainName.contains("TEAM")){
                waitUntilShiftIn();
            }
            if (autoChainName.contains("TEAM")){
                // 执行 T 挂机脚本
                runMain(autoChainName,true);
            }else{
                // 执行 A 挂机脚本
                runMain(autoChainName,false);
            }
        }else{
            LOGGER.info("无后台脚本，直接执行runnable任务！");
            // 执行runnable任务
            waitUntilRunnableFinished(runnableName);
        }
        return true;

    }
    public void waitUntilRunnableFinished(String runnableName){
        LOGGER.info("执行runnable任务！");
        Runnable rn = (Runnable) MySpringUtil.getApplicationContext().getBean(runnableName);
        mainExcutor.execute(rn);
        GameUtil.delay(5000);
        ThreadUtil.waitUntilNoneThreadWithOutCount(mainExcutor);
    }
    public void waitUntilShiftOut(){
        GameUtil.delay(3000);
        reBootCounts = 0;
        LOGGER.info("标记ShiftOUT为True");
        setShiftOut(true);
        ThreadUtil.waitUntilNoneThreadWithOutCount(frontExcutor);
    }
    public void runMain(String autoChainName,boolean checkLogin){
        reBootCounts = 0;
        LOGGER.info("执行挂机脚本");
         mainExcutor.execute(new Runnable() {
            @Override
            public void run() {
                doClick(autoChainName,checkLogin);
            }
        });
    }
    public void waitUntilShiftIn(){
        reBootCounts = 0;
        LOGGER.info("执行RunningChain的ShiftIN脚本");
        mainExcutor.execute(new Runnable() {
            @Override
            public void run() {
                doShiftIn();
            }
        });
        GameUtil.delay(5000);
        ThreadUtil.waitUntilNoneThreadWithOutCount(mainExcutor);
    }
    private void doShiftIn(){
        try {
            RunningChain rc = ChainUtil.getRunningChain();
            ClickChain cc = null;
            try {
                cc = ChainUtil.getClickChain(rc.getAutoChainName());
            } catch (Exception e) {
                LOGGER.error(e.getMessage(),e);
            }
            if(goInfor.contains("" + cc.getLdIndex())){
                throw new AppNeedStopException();
            }
            if (reBootCounts == 5){
                reBootCounts = 0;
                goInfor += cc.getLdIndex() + "_";
                throw new AppNeedStopException();
            }
            doClickInner(ChainUtil.getShiftIningPathReflash());
        } catch (AppNeedRestartException e) {
            reBootCounts++;
            LOGGER.error(e.getMessage(),e);
            // 重新登录，切出，再切入
            LOGGER.info("切入失败，重新登录切出再切入！");
            setShiftOut(true);
            reBootFromRunningChain();
            doShiftIn();
            LOGGER.info("再次切入完毕！");
        } catch (AppNeedStopException e) {
            LOGGER.info("重启超过10次，终止切入！");
        }
    }
    private void closeLdForRunning(String path){
        ClickChain cc = null;
        try {
            cc = ChainUtil.getClickChain(path);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(),e);
        }
        ProcessDealUtil.closeLD(cc.getLdIndex());
    }
    /** 登录操作 **/
    private void doLogin(String scriptPath, boolean ifReBoot) throws AppNeedStopException, AppNeedRestartException, AppNeedUpdateException {
        RunningChain rc = ChainUtil.getRunningChain();
        if (rc.isLogin() || ifReBoot){
            LOGGER.info("开始登陆！");
            ClickChain cc = null;
            try {
                cc = ChainUtil.getClickChain(scriptPath);
            } catch (Exception e) {
                LOGGER.error(e.getMessage(),e);
                return;
            }
            String apkPackageName = cc.getApkPackageName();
            String loginChainName = cc.getLoginChainName();
            PointColor moveFromPC = cc.getMoveFromPC();
            PointColor moveToPC = cc.getMoveToPC();
            int ldIndex = cc.getLdIndex();
            ProcessDealUtil.startApp(ldIndex,apkPackageName,false);
            List<PointColor> pocoList = new ArrayList<PointColor>();
            pocoList.add(new PointColor(moveFromPC.getPoint(), moveFromPC.getColor(), true));
            GameUtil.waitUntilAllColor(pocoList, GameConstant.DELAY, Constant.EXMonitor);
            // 移动窗口至左上角
            GameUtil.moveToLeftTop(moveFromPC.getPoint(),moveToPC.getPoint());
            String newScriptPath = scriptPath + "/" + loginChainName;
            GameUtil.delay(25* 1000);
//            ProcessDealUtil.cpFileForLastOrigion(ldIndex);
            GameUtil.delay(5* 1000);
            doClickInner(newScriptPath);
        }
    }
    /** 执行操作链 **/
    private void stopClick(){
        setAllStop(true);
        try {
            ThreadUtil.waitUntilNoneThread(guardExcutor);
            ThreadUtil.waitUntilNoneThread(frontExcutor);
        } catch (AppNeedRestartException e) {
            LOGGER.error(e.getMessage(),e);
        }

    }
    private void doClickInner(String scriptPath) throws AppNeedRestartException, AppNeedStopException {
        LOGGER.info("运行脚本路径：" + scriptPath);
        List<ClickUnit> mainCulist;
        ClickChain cc;
        try {
            mainCulist = ChainUtil.getClickUnits(scriptPath,true);
            cc = ChainUtil.getClickChain(scriptPath);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(),e);
            return;
        }
        // 初始化循环变量
        setGo(true);
        setAllStop(false);

        int size = mainCulist.size();
        long lastClickTimeStamp = System.currentTimeMillis();
        long startClickTimeStamp = System.currentTimeMillis();
        long lastResultTimeStamp = System.currentTimeMillis();
        //点击单元
        ClickUnit tempCu;
        // 临时颜色
        Color tempColor;
        // 临时颜色
        String tempNum = null;
        // 检测点色集合
        List<PointColor> tempCheckPcList;
        // 点击点色集合
        List<PointColor> tempClickPcList;
        // 检测点色集合大小
        int checkListSize;
        // 点击点色集合大小
        int clickListSize;
        // 是否点击
        boolean ifClick;
        //  次数A
        int checkCountA;
        //  次数B
        int checkCountB;
        //  次数C
        int checkCountC = 0;
        //  次数D
        int checkCountD = 0;
        // 临时点色
        PointColor temPC;
        Map<Integer, Integer> limits = new HashMap<>();
        //添加最大次数map
        for (int i = 0; i < size; i++) {
            tempCu = mainCulist.get(i);
            limits.put(i, tempCu.getClickLimits());
        }
        // 遍历点击单元，判断点色，执行操作
        while (isGo() && !isAllStop()){
            // 遍历点击单元ClickUnit
            for (int i = 0; i < size ; i++) {
                tempCu = mainCulist.get(i);
                tempCheckPcList = tempCu.getCheckList();
                checkListSize = tempCheckPcList.size();
                // 循环检测颜色点
                ifClick = true;
                checkCountA = 0;
                checkCountB = 0;
                for (int j = 0; j < checkListSize; j++) {
                    temPC = tempCheckPcList.get(j);
                    tempColor = GameUtil.getScreenPixel(temPC.getPoint());
                    if (temPC.isEqual()){
                        if(temPC.isConfirm()){
                            if (GameUtil.likeEqualColor(tempColor, temPC.getColor())){
                                ifClick= false;
                                break;
                            }
                        }else{
                            if (GameUtil.likeEqualColor(tempColor, temPC.getColor())){
                                checkCountA++;
                            }else{
                                ifClick= false;
                                break;
                            }
                        }

                    }else{
                        if (!GameUtil.likeEqualColor(tempColor, temPC.getColor())){
                            checkCountB++;
                        }
                    }
                }
                //如果全部循环，说明颜色判断正确，执行点击
                if (ifClick &&
                        (checkCountA == checkListSize || checkCountB > 0)
                ){
                    //停止点 点击前
                    if (tempCu.isStopBeforeClick()){
                        setAllStop(true);
                        break;
                    }
                    // 点击次数限制
                    limits.put(i,limits.get(i)-1);
                    if (limits.get(i) == 0) {
                        mainCulist.remove(i);
                        size = mainCulist.size();
                        //停止点 超过次数
                        if (tempCu.isStopAfterLimit()){
                            setGo(false);
                            LOGGER.info("！");
                            break;
                        }
                    }
                    if(null !=tempNum && tempNum.equals(tempCu.getcNum())){
                        GameUtil.delay(cc.getClickEqualDelay());
                        tempNum = null;
                        checkCountD++;
                        break;
                    }else{
                        if(null !=tempNum){
                            checkCountD=0;
                        }
                    }

                    tempClickPcList = tempCu.getClickList();
                    clickListSize = tempClickPcList.size();
                    // 点击前延时
                    GameUtil.delay(tempCu.getDelayBeforeClick());
                    // 遍历点击点，执行点击操作
                    for (int k = 0; k < clickListSize; k++) {
                        for (int l = 0; l < tempCu.getClickCounts(); l++) {
                            temPC = tempClickPcList.get(k);
                            GameUtil.getMymouse().mouseMoveByPoint(new Point((int) temPC.getPoint().getX(), (int) temPC.getPoint().getY()),true,true);
                            GameUtil.getMymouse().mousePressAndRelease(50);

                            // 单双三。。。延时
                            GameUtil.delay(tempCu.getClickCountsDelay());
                        }
                        // 顺序点击延时
                        GameUtil.delay(tempCu.getClickListDelay());
                    }

                    // 点击后延时
                    GameUtil.delay(tempCu.getDelayAfterClick());
                    GameUtil.delay(cc.getClickDelay());
                    //如果有子操作名称，执行子操作
                    if(!StringUtils.isEmpty(tempCu.getChildChainName())){
                        String newScriptPath = scriptPath + "/" + tempCu.getChildChainName();
                        doClickInner(newScriptPath);
                        setGo(true);
                    }
                    // 记录操作编码
                    tempNum = tempCu.getcNum();
                    // 添加点击时间戳
                    lastClickTimeStamp = System.currentTimeMillis();
                    // 添加成果时间戳
                    if (tempCu.isCountResult()){
                        lastResultTimeStamp = System.currentTimeMillis();
                        reBootCounts = 0;
                    }
                    //停止点 点击后
                    if (tempCu.isStopAfterClick()){
                        setAllStop(true);
                        break;
                    }
                }
                // 单元判断延时
                GameUtil.delay(cc.getCheckDelay());
            }
            // 暂停策略
            GameUtil.ifPauseScript();
            // 检测各种策略
            if (checkCountC%5 == 0){
                doClickCheck(cc,startClickTimeStamp,lastClickTimeStamp,lastResultTimeStamp,scriptPath, checkCountD);
            }

        }
        LOGGER.info("脚本路径：" + scriptPath + " 点击结束了!");
    }
    private boolean doClickCheck(ClickChain cc,
                              long startClickTimeStamp,
                              long lastClickTimeStamp,
                              long lastResultTimeStamp,
                              String scriptPath,
                                 int checkCountD) throws AppNeedRestartException {
        // 超时策略
        if (cc.isThrowExceptionOutTime()){
            // 硬超时 执行时间超时 重启
            if ((System.currentTimeMillis() - startClickTimeStamp) > cc.getStopOutTime()){
                LOGGER.info("执行时间超时！");
                throw new AppNeedRestartException();
            }
        }else{
            // 软超时 最后点击时间超时 停止
            if (cc.getStopOutTime() != -1
                    && (System.currentTimeMillis() - lastClickTimeStamp)
                    > cc.getStopOutTime()){
                setGo(false);
                LOGGER.info("最后点击时间超时！");
                return false;
            }
        }
        // 无战斗成果超时策略
        if (cc.isResultGo()){
            // 无战斗成果超时 重启
            if ((System.currentTimeMillis() - lastResultTimeStamp) > cc.getResultOutTime()){
                LOGGER.info("无战斗成果超时！");
                throw new AppNeedRestartException();
            }
        }
        // 某点次数过多 策略
        if (checkCountD > 30 && !scriptPath.contains("LOGIN")){
            // 某点次数过多
            LOGGER.info("同一操作执行过多！重新启动脚本！");
            throw new AppNeedRestartException();
        }
        // 如果是切出操作
        if (isShiftOut()
                && !scriptPath.contains("CLICK_EX_SUB")
                && !scriptPath.contains("LOGIN")
                && !scriptPath.contains("SHIFTIN") ){
            LOGGER.info("执行切出操作！");
            setShiftOut(false);
            String shiftOutPath = scriptPath + "/" + cc.getShiftOutChainName();
            String shiftInPath = scriptPath + "/" + cc.getShiftInChainName();
            // 保存正在运行的chain路径（切入脚本路径）
            RunningChain rc = ChainUtil.getRunningChain();
            rc.setShiftIningPath(shiftInPath);
            ChainUtil.saveRunningChain(rc);
            // 执行shift out 操作
            try {
                doClickInner(shiftOutPath);
            } catch (AppNeedRestartException e) {
                setShiftOut(true);
                throw e;
            } catch (AppNeedStopException e) {
                e.printStackTrace();
            }
            // 执行完停止所有
            setAllStop(true);
            return false;
        }
        return true;
    }
    /** 设置点击json **/
    public static void setClicker(){
        ClickUnit cu;
        List<ClickUnit> cuList = getCuList();
        PointColor pc = getMousePointColor();
        if (cuList!=null && cuList.size() > 0){
            cu = cuList.get(cuList.size()-1);
            // 添加检测点
            if (cu.getCheckList() != null || cu.getCheckList().size() > 0){
                cu.getClickList().add(pc);
            }else{
                JOptionPane.showMessageDialog(null, "未设置检测点！", "信息", JOptionPane.WARNING_MESSAGE);
            }
        }else{
            JOptionPane.showMessageDialog(null, "没找到操作json！", "信息", JOptionPane.WARNING_MESSAGE);
        }
        String text = JSONArray.toJSONString(cuList);
        ChainUtil.saveFile(text,NativeCp.getUserDir() + "/config/"+ Constant.CLICK_EX + "/temp/temp.json");
    }
    /** 设置检测json **/
    public static void setChecker(){
        ClickUnit cu;
        List<ClickUnit> cuList = getCuList();
        PointColor pc = getMousePointColor();
        if (cuList!=null && cuList.size() > 0){
            cu = cuList.get(cuList.size()-1);
            // 添加检测点
            if (cu.getClickList() == null || cu.getClickList().size() == 0){
                cu.getCheckList().add(pc);
            }else{
                addNewClickUnit(cuList,cu,pc);
            }
        }else{
            cuList = new ArrayList<>();
            cu = new ClickUnit();
            addNewClickUnit(cuList,cu,pc);
        }
        String text = JSONArray.toJSONString(cuList);
        ChainUtil.saveFile(text,NativeCp.getUserDir() + "/config/"+ Constant.CLICK_EX + "/temp/temp.json");
    }
    private static List<ClickUnit> getCuList(){
        List<ClickUnit> cuList = null;
        try {
            cuList = ChainUtil.getClickUnits("temp",false);
        } catch (Exception e) {
            LOGGER.error(e.getMessage(),e);
        }
        return cuList;
    }
    private static PointColor getMousePointColor(){
        Point p = GameUtil.getMousePosition();
        Color c = GameUtil.getScreenPixel(p);

        PointColor pc = new PointColor();
        pc.setPoint(p);
        pc.setColor(c);
        pc.setEqual(true);
        return pc;
    }
    private static void addNewClickUnit(List<ClickUnit> cuList, ClickUnit cu, PointColor pc){
        cu = new ClickUnit();
        List <PointColor> pcList = new ArrayList<>();
        pcList.add(pc);
        cu.setCheckList(pcList);

        cu.setClickCounts(1);
        cu.setClickCountsDelay(0);

        cu.setClickLimits(-1);
        cu.setClickListDelay(0);
        cu.setDelayAfterClick(0);
        cu.setDelayBeforeClick(0);
        cu.setClickListDelay(100);
        cu.setDelayAfterClick(500);
        cu.setStopAfterClick(false);
        cu.setStopBeforeClick(false);
        cu.setStopAfterLimit(true);
        cu.setSubCheckRootPath("");
        cu.setSubCheckPathList(new ArrayList<>());
        cu.setcNum(System.currentTimeMillis()+"");
        cu.setClickList(new ArrayList<>());
        cuList.add(cu);
    }

    public static void main(String[] args) {
//        CronTrigger ct= new CronTrigger("0 0 0/1 * * ? ");
//        Date dt = ct.nextExecutionTime(new TriggerContext() {
//            @Override
//            public Date lastScheduledExecutionTime() {
//                return null;
//            }
//
//            @Override
//            public Date lastActualExecutionTime() {
//                return null;
//            }
//
//            @Override
//            public Date lastCompletionTime() {
//
//                return new Date();
//            }
//        });
//        System.out.println(dt.toString());
//        if(new Date().getTime() + 5 * 60 * 1000 < dt.getTime()) {
//            ProcessDealUtil.sleepComputer();
//        }
    }

    private boolean isGo() {
        return go;
    }

    private void setGo(boolean go) {
        this.go = go;
    }

    public boolean isAllStop() {
        return allStop;
    }

    public void setAllStop(boolean allStop) {
        this.allStop = allStop;
    }

    public void setFrontExcutor(ThreadPoolTaskExecutor frontExcutor) {
        this.frontExcutor = frontExcutor;
    }

    public void setGuardExcutor(ThreadPoolTaskExecutor guardExcutor) {
        this.guardExcutor = guardExcutor;
    }

    public boolean isShiftOut() {
        return shiftOut;
    }

    public void setShiftOut(boolean shiftOut) {
        this.shiftOut = shiftOut;
    }

    public void setMainExcutor(ThreadPoolTaskExecutor mainExcutor) {
        this.mainExcutor = mainExcutor;
    }

}
